package com.shanzmoo.db.report.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shanzmoo.db.mall.entity.MallOrderEntity;
import com.shanzmoo.db.mall.service.IMallOrderService;
import com.shanzmoo.db.order.entity.OutletOrderEntity;
import com.shanzmoo.db.order.service.IOutletOrderService;
import com.shanzmoo.db.personnel.entity.MemberInfoEntity;
import com.shanzmoo.db.personnel.service.IMemberInfoService;
import com.shanzmoo.db.product.entity.ProductSpuEntity;
import com.shanzmoo.db.product.service.IProductSpuService;
import com.shanzmoo.db.report.entity.vo.OrderTradeTrend;
import com.shanzmoo.db.report.entity.vo.ProductSalesVO;
import com.shanzmoo.db.report.entity.vo.StatisticsVO;
import com.shanzmoo.db.report.service.IndexService;
import com.shanzmoo.db.third.entity.PlatformOrderEntity;
import com.shanzmoo.db.third.service.IPlatformOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 *
 *
 * @author： Gzhao 2021/1/23
 */
@Service
public class IndexServiceImpl implements IndexService {

    @Autowired
    private IMemberInfoService memberInfoService;
    @Autowired
    private IProductSpuService productSpuService;
    @Autowired
    private IOutletOrderService outletOrderService;
    @Autowired
    private IMallOrderService mallOrderService;
    @Autowired
    private IPlatformOrderService platformOrderService;

    @Override
    public StatisticsVO getStatistics() {
        StatisticsVO statisticsVO = new StatisticsVO();

        int memberTotal = memberInfoService.count(
                new QueryWrapper<MemberInfoEntity>()
                        .eq("deleted", false)
        );
        int memberThisMonthAdd = memberInfoService.count(
                new QueryWrapper<MemberInfoEntity>()
                        .eq("deleted", false)
                        .ge("create_time", LocalDateTimeUtil.format(
                                LocalDateTimeUtil.offset(LocalDateTime.now(), -1, ChronoUnit.DAYS),
                                "yyyy-MM-01 00:00:00"))
        );
        int memberYesterdayAdd = memberInfoService.count(
                new QueryWrapper<MemberInfoEntity>()
                        .eq("deleted", false)
                        .ge("create_time", LocalDateTimeUtil.format(
                                LocalDateTimeUtil.offset(LocalDateTime.now(), -1, ChronoUnit.DAYS),
                                "yyyy-MM-01 00:00:00"))
                        .le("create_time", LocalDateTimeUtil.format(
                                LocalDateTimeUtil.offset(LocalDateTime.now(), -1, ChronoUnit.DAYS),
                                "yyyy-MM-01 00:00:00"))
        );
        statisticsVO.setMember(memberTotal, memberThisMonthAdd, memberYesterdayAdd);

        int spuTotal = productSpuService.count(
                new QueryWrapper<ProductSpuEntity>()
                        .eq("deleted", false)
        );
        int spuOnSale = productSpuService.count(
                new QueryWrapper<ProductSpuEntity>()
                        .eq("deleted", false)
                        .eq("status", true)
        );
        int spuOffSale = productSpuService.count(
                new QueryWrapper<ProductSpuEntity>()
                        .eq("deleted", false)
                        .eq("status", false)
        );
        statisticsVO.setSpu(spuTotal, spuOnSale, spuOffSale);

        int outlet = outletOrderService.count(
                new QueryWrapper<OutletOrderEntity>()
                        .eq("deleted", false)
                        .in("status", 0, 1, 2, 3, 4)
        );
        int mall = mallOrderService.count(
                new QueryWrapper<MallOrderEntity>()
                        .eq("deleted", false)
                        .in("status", 0, 1, 2, 3)
        );
        int thirdPPlatform = platformOrderService.count(
                new QueryWrapper<PlatformOrderEntity>()
                        .eq("deleted", false)
                        .in("status", 0, 1, 2, 3)
        );
        statisticsVO.setOrder(outlet, mall, thirdPPlatform);

        List<OutletOrderEntity> outletOrderList = outletOrderService.list(
                new QueryWrapper<OutletOrderEntity>()
                        .eq("deleted", false)
                        .in("status", 0, 1, 2, 3, 4)
                        .eq("pay_status", true)
        );
        double salesOutlet = outletOrderList.stream().mapToDouble(e->e.getReceiveAmount().doubleValue()).sum();

        List<MallOrderEntity> mallOrderList = mallOrderService.list(
                new QueryWrapper<MallOrderEntity>()
                        .eq("deleted", false)
                        .in("status", 1, 2, 3)
                        .eq("pay_status", true)
        );
        double salesMall = mallOrderList.stream().mapToDouble(e->e.getReceiveAmount().doubleValue()).sum();

        List<PlatformOrderEntity> platformOrderList = platformOrderService.list(
                new QueryWrapper<PlatformOrderEntity>()
                        .eq("deleted", false)
                        .in("status", 1, 2, 3)
        );
        double salesThirdPlatform = platformOrderList.stream().mapToDouble(e->e.getReceiveAmount().doubleValue()).sum();

        statisticsVO.setSalesData(salesOutlet, salesMall, salesThirdPlatform);

        return statisticsVO;
    }

    @Override
    public List<OrderTradeTrend> getRootOrderTrend() {
        List<OrderTradeTrend> result = obtainLastSixMonth();

        for (OrderTradeTrend orderTradeTrend : result) {
            String[] timeArray = orderTradeTrend.getMonth().split("\\.");
            String startTime = timeArray[0] + "-" + timeArray[1] + "-01 00:00:00";

            String endTime = LocalDateTimeUtil.format(
                    LocalDateTimeUtil.offset(LocalDateTimeUtil.parse(startTime, "yyyy-MM-dd HH:mm:ss"),
                            1, ChronoUnit.MONTHS),
                    "yyyy-MM-dd HH:mm:ss");

            List<OutletOrderEntity> outletOrderList = outletOrderService.list(
                    new QueryWrapper<OutletOrderEntity>()
                            .eq("deleted", false)
                            .in("status", 0, 1, 2, 3, 4)
                            .eq("pay_status", true)
                            .ge("create_time", startTime)
                            .lt("create_time", endTime)
            );

            orderTradeTrend.setOrderNum(outletOrderList.size());
            orderTradeTrend.setTotalMoney(outletOrderList.stream().mapToDouble(e->e.getReceiveAmount().doubleValue()).sum());
        }
        return result;
    }

    @Override
    public List<OrderTradeTrend> getMallOrderTrend() {
        List<OrderTradeTrend> result = obtainLastSixMonth();

        for (OrderTradeTrend orderTradeTrend : result) {
            String[] timeArray = orderTradeTrend.getMonth().split("\\.");
            String startTime = timeArray[0] + "-" + timeArray[1] + "-01 00:00:00";

            String endTime = LocalDateTimeUtil.format(
                    LocalDateTimeUtil.offset(LocalDateTimeUtil.parse(startTime, "yyyy-MM-dd HH:mm:ss"),
                            1, ChronoUnit.MONTHS),
                    "yyyy-MM-dd HH:mm:ss");

            List<MallOrderEntity> mallOrderList = mallOrderService.list(
                    new QueryWrapper<MallOrderEntity>()
                            .eq("deleted", false)
                            .in("status", 1, 2, 3)
                            .eq("pay_status", true)
                            .ge("create_time", startTime)
                            .lt("create_time", endTime)
            );

            orderTradeTrend.setOrderNum(mallOrderList.size());
            orderTradeTrend.setTotalMoney(mallOrderList.stream().mapToDouble(e->e.getReceiveAmount().doubleValue()).sum());
        }
        return result;
    }

    @Override
    public List<OrderTradeTrend> getThirdPlatformOrderTrend() {
        List<OrderTradeTrend> result = obtainLastSixMonth();

        for (OrderTradeTrend orderTradeTrend : result) {
            String[] timeArray = orderTradeTrend.getMonth().split("\\.");
            String startTime = timeArray[0] + "-" + timeArray[1] + "-01 00:00:00";

            String endTime = LocalDateTimeUtil.format(
                    LocalDateTimeUtil.offset(LocalDateTimeUtil.parse(startTime, "yyyy-MM-dd HH:mm:ss"),
                            1, ChronoUnit.MONTHS),
                    "yyyy-MM-dd HH:mm:ss");

            List<PlatformOrderEntity> platformOrderList = platformOrderService.list(
                    new QueryWrapper<PlatformOrderEntity>()
                            .eq("deleted", false)
                            .in("status", 1, 2, 3)
                            .ge("create_time", startTime)
                            .lt("create_time", endTime)
            );

            orderTradeTrend.setOrderNum(platformOrderList.size());
            orderTradeTrend.setTotalMoney(platformOrderList.stream().mapToDouble(e->e.getReceiveAmount().doubleValue()).sum());
        }
        return result;
    }

    @Override
    public List<ProductSalesVO> getProductSalesSort() {
        List<ProductSalesVO> list = new ArrayList<>();

        list.addAll(outletOrderService.getProductSales());
        list.addAll(mallOrderService.getProductSales());
        list.addAll(platformOrderService.getProductSales());

        Collections.sort(list, ((o1, o2) -> {
            return (int)(o2.getTotalMoney().doubleValue() - o1.getTotalMoney().doubleValue());
        }));

        return CollectionUtil.sub(list, 0, 9);
    }

    private List<OrderTradeTrend> obtainLastSixMonth() {
        List<OrderTradeTrend> result = new ArrayList<>(6);
        for (int i = 5; i > -1; i--) {
            String month = LocalDateTimeUtil.offset(LocalDateTime.now(), -i, ChronoUnit.MONTHS)
                    .format(DateTimeFormatter.ofPattern("yyyy.MM"));

            result.add(OrderTradeTrend.builder().month(month).build());
        }

        return result;
    }

}
